import { Prefab, _decorator, Node, instantiate } from "cc";
import { Unit } from "../Entity/Unit";

const { ccclass, property } = _decorator;

@ccclass
export default class PoolManager {
    private static pools: Map<string, ObjectPool> = new Map();

    static pool_all_num: number = 0;
    /**
     * 获取对象池，如果不存在则创建一个新的
     * @param prefab 预制体
     * @returns 对象池实例
     */
    static getPool(prefab: Prefab | string): ObjectPool {
        const poolKey = typeof prefab === 'string' ? prefab : prefab.name;

        // 如果池子已经存在，则直接返回
        if (this.pools.has(poolKey)) {
            return this.pools.get(poolKey)!;
        }

        if (typeof prefab !== 'string') {
            // 如果池子不存在，创建新的对象池并存储
            const newPool = new ObjectPool(prefab);
            this.pools.set(poolKey, newPool);

            return newPool;
        }
        else {
            console.log('警告==>不存在该池！请先传入预制体！');
            return;
        }
    }

    /**
     * 获取对象
     * @param prefab 预制体
     * @param parentNode 父节点
     * @param notActive 从池中取对象时，不激活
     * @returns 从对象池中获取的对象
     */
    static getNode(prefab: Prefab | string, notActive = false): Node {
        const pool = this.getPool(prefab);
        return pool.get(notActive);
    }

    /**
     * 回收对象
     * @param prefab 预制体
     * @param node 回收的节点
     */
    static putNode(prefab: Prefab | string, node: Node): boolean {
        const poolKey = typeof prefab === 'string' ? prefab : prefab.name;

        // 检查对象池是否存在
        if (this.pools.has(poolKey)) {
            const pool = this.pools.get(poolKey);
            pool.put(node);
            this.pool_all_num++;

            if (this.pool_all_num > 500) {
                this.clearAllPools();
            }

            return true;
        }
        else {
            console.log(`回收失败，还不存在${poolKey}该类型的对象池，请先用预制体创建该池！`);
            return false;
        }
    }

    /**
     * 清除所有对象池
     */
    static clearAllPools() {
        this.pools.forEach(pool => pool.clear());
        // this.pools.clear();
        this.pool_all_num = 0;
    }
}

class ObjectPool {
    private pool: Node[] = [];
    private prefab: Prefab;

    constructor(prefab: Prefab) {
        this.prefab = prefab;
    }

    get(notActive = false): Node {
        let node: Node;
        if (this.pool.length > 0) {
            PoolManager.pool_all_num--;
            node = this.pool.pop()!;
        } else {
            node = instantiate(this.prefab);
            let unit = node.getComponent(Unit);
            if (unit) {
                // console.log('新增', this.prefab.name)
                unit.prefabName = this.prefab.name;
            }
        }
        node.active = !notActive;
        return node;
    }

    put(node) {
        if (!this.pool.includes(node)) {
            node.active = false;
            node.setParent(null);
            this.pool.push(node);
        }
    }

    clear() {
        this.pool.forEach(node => node.destroy());
        this.pool = [];
    }
}
